package main
 
import (
    "fmt"
    "log"
    "net/http"
    "os/exec"
    "os"
    "io/ioutil"
    "strings"
    "time"
)

type Config struct {
    Webroot string
    Listen string
    Acl []string
}

func NewConfig() *Config {
    v := &Config{}
    v.Webroot = "/data/acme"
    v.Listen = ":9090"
    v.Acl = make([]string, 0)
    return v
}

var g_config *Config
var mainlog *log.Logger = nil 
var mgtlog  *log.Logger = nil 
var domain, token, api string
var uid float64
var id float64

func loadConfig() *Config {

    c := NewConfig()
    buf, err := ioutil.ReadFile("/etc/caproductor/default.ini")
    if err != nil {
        mainlog.Println("read config file failed, use default config webroot=/data/acme port=9090.", err)
        return c
    }
    lines := strings.Split(string(buf), "\n")
    for _ , line := range lines {
        line = strings.TrimSpace(line)
        if line == "" || line[0] == ';' {
            continue
        }
        
        if strings.Index(line, "acl=") == 0 {
            c.Acl = strings.Split(strings.TrimSpace(line[4:]), ",")
        } else if strings.Index(line, "webroot=") == 0 {
            c.Webroot = strings.TrimSpace(line[8:])
        } else if strings.Index(line, "listen=") == 0 {
            c.Listen = strings.TrimSpace(line[7:])
        }
    }
    return c
}

func setuplog() {

    f, err := os.OpenFile("/var/log/caproductor.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
    if err != nil {
        log.Println("open log file failed.", err)
        return
    }
    mainlog  = log.New(f, "", log.Ldate|log.Ltime)
}

func savepid() {

    s := fmt.Sprintf("%d", os.Getpid())
    err := ioutil.WriteFile("/var/run/caproductor.pid", []byte(s), 0644)
    if err != nil {
        mainlog.Println("write pid file failed.", err)
    }
}

func setupmgtlog() {

    f, err := os.OpenFile("/var/log/caproductor_monitor.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
    if err != nil {
        log.Println("open log file failed.", err)
        return
    }
    mgtlog  = log.New(f, "", log.Ldate|log.Ltime)
}

func main() {

    daemon := true
    child := true
    for _,arg := range os.Args[1:] {
        if arg == "--no-daemon" {
            daemon = false
        } else if arg == "--no-child" {
            child = false
        }
    }
    if daemon {
        args := append(os.Args, "--no-daemon")
        cmd := exec.Command(args[0], args[1:]...)
        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        err := cmd.Start()
        if err != nil {
            fmt.Println("start daemon faild.", err)
        }
        return
    }
    if child {

        setupmgtlog()
        savepid()
        for {
            args := append(os.Args, "--no-child")
            cmd := exec.Command(args[0], args[1:]...)
            err := cmd.Start()
            if err != nil {
                mgtlog.Println("start child process failed.", err)
                time.Sleep(1 * time.Second)
                continue
            }
            mgtlog.Printf("child worker running. pid %d", cmd.Process.Pid)
            err = cmd.Wait()
            if err != nil {
                mgtlog.Printf("wait child worker failed. restart it after 1s. (%s)", err.Error())
                time.Sleep(1 * time.Second)
                continue
            }
            mgtlog.Printf("child worker exited. restart it after 5s. pid %d", cmd.Process.Pid)
            time.Sleep(5 * time.Second)
        }
        return
    }

    setuplog()
    g_config = loadConfig()

    http.HandleFunc("/", hander)
    
    addr := "0.0.0.0"

    mainlog.Println("addr+listen:", addr + g_config.Listen)

    err := http.ListenAndServe(addr + g_config.Listen, nil)
    if err != nil {
        log.Println("ListenAndServe: ", err)
    }
}